﻿namespace EventBusNet6;
/// <summary>
/// 命令执行
/// </summary>
public class CommandService
{

    private readonly static ConcurrentQueue<IExecuteCommand> tasks = new ConcurrentQueue<IExecuteCommand>();

    private static CommandService _instance = null;
    private static readonly object _instanceLock = new object();
    /// <summary>          
    /// 获取实例(单例模式)        
    /// </summary>          
    /// <returns></returns>          
    public static CommandService GetInstance()
    {
        if (_instance == null)
            lock (_instanceLock)
                if (_instance == null)
                {
                    _instance = new CommandService();
                }
        return _instance;
    }


    public void Add(IExecuteCommand cmd)
    {
        tasks.Enqueue(cmd);
    }
    public void AddRange(IEnumerable<IExecuteCommand> cmds)
    {
        foreach (var cmd in cmds)
            tasks.Enqueue(cmd);
    }

    public void RunAsync(CancellationToken stoppingToken, Func<IExecuteCommand, bool> canExcute = null, Action<IExecuteCommand> onCompleted = null)
    {
        IExecuteCommand cmd;
        while (!stoppingToken.IsCancellationRequested)
        {
            while (tasks.TryDequeue(out cmd))
            {
                if (canExcute == null || canExcute(cmd))
                {
                    using (var process = new Process())
                    {
                        process.StartInfo.FileName = cmd.ExePath;
                        process.StartInfo.Arguments = cmd.Arguments;
                        process.StartInfo.UseShellExecute = false;
                        process.StartInfo.RedirectStandardOutput = true;
                        process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
                        
                        process.OutputDataReceived += (sender, e) =>
                        {
                            if (!string.IsNullOrEmpty(e.Data))
                            {
                                cmd.OutData.Append(e.Data);
                            }
                        };
                        
                        process.Start();

                        process.BeginOutputReadLine();
                        process.WaitForExit();

                        process.Close();

                        onCompleted?.Invoke(cmd);
                    }
                }
            }
        }
    }

    public void RunExePath(IExecuteCommand cmd,Func<IExecuteCommand, bool> canExcute = null, Action<IExecuteCommand> onCompleted = null)
    {
     
        if (canExcute(cmd))
        {
            using (var process = new Process())
            {
               
                process.StartInfo.FileName = cmd.ExePath;
                process.StartInfo.Arguments = cmd.Arguments;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
                process.OutputDataReceived += (sender, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        cmd.OutData.Append(e.Data);
                    }
                };
                process.Start();

                process.BeginOutputReadLine();
                process.WaitForExit();

                process.Close();

                onCompleted?.Invoke(cmd);
            }
        }
    }

}
